package com.gitee.minimalismstyle.fresh.common.data.beetl.custom

import org.beetl.sql.clazz.ColDesc
import org.beetl.sql.clazz.TableDesc
import org.beetl.sql.clazz.kit.BeetlSQLException
import org.beetl.sql.clazz.kit.Plugin
import org.beetl.sql.core.ConnectionSource
import org.beetl.sql.core.db.DBStyle
import org.beetl.sql.core.meta.SchemaMetadataManager
import java.sql.Connection
import java.sql.ResultSet
import java.sql.SQLException

@Plugin
class FreshSchemaMetadataManager(ds : ConnectionSource,  style: DBStyle): SchemaMetadataManager(ds, style) {
    private var checkAuto = true

    override fun getTable(name: String?): TableDesc {
        var table: TableDesc? = getTableFromMap(name)
                ?: throw BeetlSQLException(BeetlSQLException.TABLE_NOT_EXIST, "table \"$name\" not exist")

        if (table?.cols?.size == 0) {
            table = initTable(table)
        }

        return table!!
    }

    /**
     * 获得某一个表的描述
     * @param desc
     * @return
     */
    private fun initTable(desc: TableDesc): TableDesc? {
        synchronized(desc) {

            //先创建一个临时TableDesc，避免并发访问desc
            if (!desc.cols.isEmpty()) {
                //已经加载
                return desc
            }
            val temp = FreshTableDesc(desc.name, desc.remark)
            temp.realTableName = desc.realTableName
            temp.catalog = desc.catalog
            temp.schema = desc.schema
            var conn: Connection? = null
            var rs: ResultSet? = null
            val tableName = if (desc.realTableName != null) desc.realTableName else desc.name
            return try {
                val catalog = temp.catalog
                var schema = temp.schema
                schema = this.getDbSchema(schema)
                conn = ds.metaData
                val dbmd = conn.metaData
                rs = dbmd.getPrimaryKeys(catalog, schema, tableName)
                while (rs.next()) {
                    val idName = rs.getString("COLUMN_NAME")
                    temp.addIdName(idName)
                }
                rs.close()
                rs = dbmd.getColumns(catalog, schema, tableName, "%")
                while (rs.next()) {
                    val colName = rs.getString("COLUMN_NAME")
                    val sqlType = rs.getInt("DATA_TYPE")
                    val size = rs.getInt("COLUMN_SIZE")
                    val o = rs.getObject("DECIMAL_DIGITS")
                    val isNullable = rs.getObject("IS_NULLABLE") as String
                    var digit: Int? = null
                    if (o != null) {
                        digit = (o as Number).toInt()
                    }
                    val remark = rs.getString("REMARKS")
                    val col = ColDesc(colName, sqlType, size, digit, remark, isNullable)
                    try {
                        if (checkAuto) {
                            val auto = rs.getString("IS_AUTOINCREMENT")
                            if (auto != null && auto == "YES") {
                                col.isAuto = true
                            }
                        }
                    } catch (ex: SQLException) {
                        //某些驱动可能不支持
                        checkAuto = false
                    }
                    temp.addCols(col)
                }
                rs.close()
                moreInfo(temp)
                tableInfoMap[temp.name] = temp
                temp
            } catch (e: SQLException) {
                throw BeetlSQLException(BeetlSQLException.SQL_EXCEPTION, e)
            } finally {
                close(conn)
            }
        }
    }
}